﻿

using System.Text;
using System;
using IDEAMS.core.queue;
using IDEAMS.utils;

namespace IDEAMS.core.opm
{
    public static class OPM_Protocol
    {
        static OPM_Protocol()
        {

        }

        // 获取命令字
        static public OPM_CmdID GetCmd(byte[] buffer, int len)
        {
            if (buffer[0] != 0x01) return OPM_CmdID.CMD_UNKNOWN;

            OPM_CmdID cmd = OPM_CmdID.CMD_UNKNOWN;

            OPM_CmdID checkCmd = (OPM_CmdID)buffer[1];
            if (checkCmd == OPM_CmdID.CMD_READ_PARAMETER
                || checkCmd == OPM_CmdID.CMD_READ_UPLOAD_CONF
                || checkCmd == OPM_CmdID.CMD_WRITE_LOCAL_ADDR
                || checkCmd == OPM_CmdID.CMD_WRITE_UPLOAD_CONF
                || checkCmd == OPM_CmdID.CMD_WRITE_TIME
                || checkCmd == OPM_CmdID.CMD_READ_TIME
                || checkCmd == OPM_CmdID.CMD_READ_STATUS
                || checkCmd == OPM_CmdID.CMD_START_FLAG
                || checkCmd == OPM_CmdID.CMD_READ_GRATING_WAVE_LEN
                || checkCmd == OPM_CmdID.CMD_SENSOR_UPLOAD_START_FLAG
                || checkCmd == OPM_CmdID.CMD_READ_SENSOR_UPLOAD
                || checkCmd == OPM_CmdID.CMD_WARNNING
                || checkCmd == OPM_CmdID.CMD_READ_SPECTRUM_SUMMARY
                || checkCmd == OPM_CmdID.CMD_READ_SPECTRUM
                || checkCmd == OPM_CmdID.CMD_SET_CHANNEL_PARAMETER
                || checkCmd == OPM_CmdID.CMD_READ_CHANNEL_PARAMETER
                || checkCmd == OPM_CmdID.CMD_WRITE_SENSOR_CONF
                || checkCmd == OPM_CmdID.CMD_READ_SENSOR_CONF_COUNT
                || checkCmd == OPM_CmdID.CMD_READ_SENSOR_CONF
                || checkCmd == OPM_CmdID.CMD_WRITE_SENSOR_CONF_ZERO
                || checkCmd == OPM_CmdID.CMD_SET_WAVE_OFFSET
                || checkCmd == OPM_CmdID.CMD_READ_WAVE_OFFSET
                || checkCmd == OPM_CmdID.CMD_SET_MONITOR_FREQ
                || checkCmd == OPM_CmdID.CMD_READ_MONITOR_FREQ
                || checkCmd == OPM_CmdID.CMD_WRITE_HIGHEST_PARAM
                || checkCmd == OPM_CmdID.CMD_READ_HIGHEST_PARAM
                || checkCmd == OPM_CmdID.CMD_SET_UPLOAD_WAVE_ENABLE
                || checkCmd == OPM_CmdID.CMD_READ_GRATING_CONF
                || checkCmd == OPM_CmdID.CMD_WRITE_GRATING_CONF
                || checkCmd == OPM_CmdID.CMD_WRITE_GRATING_ZERO
                || checkCmd == OPM_CmdID.CMD_READ_GRATING_WAVE_LEN_G
                || checkCmd == OPM_CmdID.CMD_READ_GRATING_WAVE_LEN_DB)
            {
                cmd = checkCmd;
            }
            return cmd;
        }

        /// <summary>
        /// 获取字节数组中字符串长度
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="maxSize"></param>
        /// <returns></returns>
        public static int GetASCIIStrLength(byte[] buffer, int offset, int maxSize)
        {
            int len = 0;
            for (int i = offset; i < offset + maxSize; i++)
            {
                if (buffer[i] != 0)
                {
                    len++;
                }
                else
                {
                    break;
                }
            }
            return len;
        }

        #region 消息解析和封装

        #region 启停消息的解析和封装
        /// <summary>
        /// 波长数据发送启停消息封装
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="control"></param>
        /// <returns></returns>
        public static int MakeStartPackage(ref byte[] buffer, StartControl control)
        {
            int offset = 0;
            buffer[offset] = control.head.cmd1; offset += 1;
            buffer[offset] = control.head.cmd2; offset += 1;
            buffer[offset] = control.startFlag; offset += 1;
            return offset;
        }

        /// <summary>
        /// 波长数据发送启停消息解析
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="len"></param>
        /// <param name="control"></param>
        /// <returns></returns>
        public static int ParseStartPackage(byte[] buffer, int len, ref StartControl control)
        {
            if(len < 3)
            {
                return -1;
            }
            control.head.cmd1 = buffer[0];
            control.head.cmd2 = buffer[1];
            control.startFlag = buffer[2];
            return 0;
        }
        #endregion

        #region 读取设备信息的封装和解析
        /// <summary>
        /// 封装读取设备信息请求
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        public static int MakeReadDeviceBaseInfoReqPackage(ref byte[] buffer, ReadDeviceBaseInfoReq req)
        {
            int offset = 0;
            buffer[offset] = req.head.cmd1; offset += 1;
            buffer[offset] = req.head.cmd2; offset += 1;
            return offset;
        }

        /// <summary>
        /// 解析设备信息
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="resp"></param>
        /// <returns></returns>
        public static int ParseReadDeviceBaseInfoRespPackage(byte[] buffer, ref ReadDeviceBaseInfoResp resp)
        {
            int offset = 0;
            int len = 0;

            // 解析头部
            resp.head.cmd1 = buffer[offset]; offset += 1;
            resp.head.cmd2 = buffer[offset]; offset += 1;

            // 设备型号（ascii）
            len = GetASCIIStrLength(buffer, offset, 16);
            resp.productModel = Encoding.ASCII.GetString(buffer, offset, len);
            offset += 16;

            // 序列号（ascii）
            len = GetASCIIStrLength(buffer, offset, 16);
            resp.seriesNumber = Encoding.ASCII.GetString(buffer, offset, len);
            offset += 16;

            // 版本（ascii）
            len = GetASCIIStrLength(buffer, offset, 16);
            resp.version = Encoding.ASCII.GetString(buffer, offset, len);
            offset += 16;

            // 本机IP地址
            Array.Copy(buffer, offset, resp.deviceIP, 0, 4);
            offset += 4;

            // 本机端口号
            ushort netValue = BitConverter.ToUInt16(buffer, offset);
            resp.devicePort = netValue;
            offset += 2;

            // 本机MAC地址
            Array.Copy(buffer, offset, resp.deviceMac, 0, 6);
            offset += 6;

            //目的IP地址
            Array.Copy(buffer, offset, resp.destIP, 0, 4);
            offset += 4;

            //目的端口号
            netValue = BitConverter.ToUInt16(buffer, offset);
            resp.destPort = netValue;
            offset += 2;

            //设备温度
            int tempValue = BitConverter.ToInt16(buffer, offset);
            resp.tempValue = tempValue / 100.0;
            offset += 2;

            //启停标志
            netValue = BitConverter.ToUInt16(buffer, offset);
            resp.startFlag = netValue;
            offset += 2;

            //通道数
            resp.nchannel = buffer[offset];
            offset += 1;

            //子网掩码
            Array.Copy(buffer, offset, resp.netMask, 0, 4);
            offset += 4;

            //默认网关
            Array.Copy(buffer, offset, resp.gateWay, 0, 4);
            offset += 4;

            // 对齐位
            resp.reserved1 = buffer[offset];
            offset += 1;

            //上报server地址
            Array.Copy(buffer, offset, resp.reportServerIP1, 0, 4);
            offset += 4;

            //上报server端口号
            netValue = BitConverter.ToUInt16(buffer, offset);
            resp.reportServerPort1 = netValue;
            offset += 2;

            //上报server地址
            Array.Copy(buffer, offset, resp.reportServerIP2, 0, 4);
            offset += 4;

            //上报server端口号
            netValue = BitConverter.ToUInt16(buffer, offset);
            resp.reportServerPort2 = netValue;
            offset += 2;

            //上报server地址
            Array.Copy(buffer, offset, resp.reportServerIP3, 0, 4);
            offset += 4;

            //上报server端口号
            netValue = BitConverter.ToUInt16(buffer, offset);
            resp.reportServerPort3 = netValue;
            offset += 2;

            //时间间隔
            uint intValue = BitConverter.ToUInt32(buffer, offset);
            resp.timeInterval = intValue;
            offset += 4;

            return 0;
        }
        #endregion

        #region 设置设备信息的封装和解析
        /// <summary>
        /// 封装设备修改请求
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        static public int MakeChangeIPReqPackage(ref byte[] buffer, ReadDeviceBaseInfoResp req)
        {
            int offset = 0;
            buffer[offset] = req.head.cmd1; offset += 1;
            buffer[offset] = req.head.cmd2; offset += 1;

            //IP地址
            Array.Copy(req.deviceIP, 0, buffer, offset, 4);
            offset += 4;

            //端口
            //short netValue = IPAddress.HostToNetworkOrder((short)req.port);
            byte[] byteValue = BitConverter.GetBytes(req.devicePort);
            Array.Copy(byteValue, 0, buffer, offset, 2);
            offset += 2;

            //MAC地址
            Array.Copy(req.deviceMac, 0, buffer, offset, 6);
            offset += 6;

            //子网掩码
            Array.Copy(req.netMask, 0, buffer, offset, 4);
            offset += 4;

            //默认网关
            Array.Copy(req.gateWay, 0, buffer, offset, 4);
            offset += 4;


            //IP地址
            Array.Copy(req.reportServerIP1, 0, buffer, offset, 4);
            offset += 4;

            //端口
            //short port1 = IPAddress.HostToNetworkOrder((short)req.reportServerPort1);
            byte[] bytePort1 = BitConverter.GetBytes(req.reportServerPort1);
            Array.Copy(bytePort1, 0, buffer, offset, 2);
            offset += 2;

            //IP地址
            Array.Copy(req.reportServerIP2, 0, buffer, offset, 4);
            offset += 4;

            //端口
            //short port2 = IPAddress.HostToNetworkOrder((short)req.reportServerPort2);
            byte[] bytePort2 = BitConverter.GetBytes(req.reportServerPort2);
            Array.Copy(bytePort2, 0, buffer, offset, 2);
            offset += 2;

            //IP地址
            Array.Copy(req.reportServerIP3, 0, buffer, offset, 4);
            offset += 4;

            //端口
            //short port3 = IPAddress.HostToNetworkOrder((short)req.reportServerPort3);
            byte[] bytePort3 = BitConverter.GetBytes(req.reportServerPort3);
            Array.Copy(bytePort3, 0, buffer, offset, 2);
            offset += 2;

            //发送间隔
            byte[] timeInterval = BitConverter.GetBytes(req.timeInterval);
            Array.Copy(timeInterval, 0, buffer, offset, 4);
            offset += 4;

            return offset;
        }
        #endregion

        #region 波长消息的解析和封装

        static private int MAX_CHANNEL = 32;

        /// <summary>
        /// 波长消息解析
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="msgLen"></param>
        /// <param name="waveLen"></param>
        /// <returns></returns>
        static public int ParseWaveLenPackage(byte[] buffer, int msgLen, ref Wave waveLen)
        {
            int offset = 0;
            waveLen.chGratting = new ChannelGrating[MAX_CHANNEL];
            waveLen.nChannel = 0;
            waveLen.cmd = 0x0C;

            // 解析头部
            offset += 2;

            // 解析body
            for (int i = 0; i < MAX_CHANNEL; i++)
            {
                if (offset >= msgLen) break;

                // 通道号
                waveLen.chGratting[i].chID = buffer[offset]; offset += 1;

                // 光栅数
                int ngrating = buffer[offset];
                waveLen.chGratting[i].ngrating = ngrating; offset += 1;

                // 预留
                offset += 1; offset += 1;

                if (ngrating > 0)
                {
                    // 根据光栅数分配波长数量
                    waveLen.chGratting[i].waveValueArray = new double[ngrating];

                    // 波长数据
                    for (int j = 0; j < ngrating; j++)
                    {
                        waveLen.chGratting[i].waveValueArray[j] = DataConverter.ToInt32(buffer, offset) / 1000.0;
                        if (waveLen.chGratting[i].waveValueArray[j] > 10000)
                        {
                            waveLen.chGratting[i].waveValueArray[j] /= 10.0;
                        }
                        offset += 4;
                    }
                }
                waveLen.nChannel++;
            }
            return 0;
        }

        /// <summary>
        /// 波长解析 设备频率大于等于2.5K    使用0x01c0指令
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="msgLen"></param>
        /// <param name="waveLen"></param>
        /// <exception cref="NotImplementedException"></exception>
        public static int ParseWaveLenGPackage(byte[] buffer, int msgLen, ref Wave waveLen)
        {
            int offset = 0;
            waveLen.chGratting = new ChannelGrating[MAX_CHANNEL];
            waveLen.nChannel = 0;
            waveLen.cmd = 0xC0;

            // 解析头部
            offset += 2;

            // 解析body
            for (int i = 0; i < MAX_CHANNEL; i++)
            {
                if (offset >= msgLen) break;

                // 通道号
                waveLen.chGratting[i].chID = buffer[offset]; offset += 1;

                // 光栅数
                int ngrating = buffer[offset];
                waveLen.chGratting[i].ngrating = ngrating; offset += 1;

                //// 预留
                //offset += 1; offset += 1;

                if (ngrating > 0)
                {
                    // 根据光栅数分配波长数量
                    waveLen.chGratting[i].waveValueArray = new double[ngrating];

                    // 波长数据
                    for (int j = 0; j < ngrating; j++)
                    {
                        waveLen.chGratting[i].waveValueArray[j] = DataConverter.ToInt16(buffer, offset) / 1000.0 + 1520;
                        offset += 2;
                    }
                }
                waveLen.nChannel++;
            }
            return 0;
        }

        /// <summary>
        /// 波长解析 同时上次波长和功率   使用0x01c1指令
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="msgLen"></param>
        /// <param name="waveLen"></param>
        /// <exception cref="NotImplementedException"></exception>
        public static int ParseWaveLenDBPackage(byte[] buffer, int msgLen, ref Wave waveLen)
        {
            int offset = 0;
            waveLen.chGratting = new ChannelGrating[MAX_CHANNEL];
            waveLen.nChannel = 0;
            waveLen.cmd = 0xC1;

            // 解析头部
            offset += 2;

            // 解析body
            for (int i = 0; i < MAX_CHANNEL; i++)
            {
                if (offset >= msgLen) break;

                // 通道号
                waveLen.chGratting[i].chID = buffer[offset]; offset += 1;

                // 光栅数
                int ngrating = buffer[offset];
                waveLen.chGratting[i].ngrating = ngrating; offset += 1;

                //// 预留
                //offset += 1; offset += 1;

                if (ngrating > 0)
                {
                    // 根据光栅数分配波长数量
                    waveLen.chGratting[i].waveValueArray = new double[ngrating];
                    waveLen.chGratting[i].dBmValue = new double[ngrating];

                    // 波长数据
                    for (int j = 0; j < ngrating; j++)
                    {
                        waveLen.chGratting[i].waveValueArray[j] = DataConverter.ToInt16(buffer, offset) / 1000.0 + 1520;
                        offset += 2;

                        byte dataL = buffer[offset]; offset += 1;
                        byte dataH = buffer[offset]; offset += 1;
                        UInt16 uValue = (UInt16)(dataL + dataH * 256);
                        Int16 value = (Int16)uValue;

                        waveLen.chGratting[i].dBmValue[j] = value / 10.0;

                    }
                }
                waveLen.nChannel++;
            }
            return 0;
        }
        #endregion

        #region 光谱summary消息的解析和封装
        /// <summary>
        /// 封装光谱summary请求
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        static public int MakeSpectrumSummaryReqPackage(ref byte[] buffer, SpectrumSummaryReq req)
        {
            int length = 0;
            buffer[0] = req.head.cmd1; length += 1;
            buffer[1] = req.head.cmd2; length += 1;

            return length;
        }
        /// <summary>
        /// 解析光谱summary消息
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="resp"></param>
        /// <returns></returns>
        static public int ParseSpectrumSummaryRespPackage(byte[] buffer, ref SpectrumSummaryResp resp)
        {
            int offset = 0;

            // 解析头部
            resp.head.cmd1 = 0x01;
            resp.head.cmd2 = 0x17;
            offset += 2;

            // 是否可以降采样
            resp.sampleQuantity = buffer[offset];
            offset += 1;

            offset += 1; // 两个字节的对齐预留
            // 波长起始值
            resp.waveLenStartValue = DataConverter.ToInt32(buffer, offset) / 1000.0;
            offset += 4;

            // 波长间隔
            double dataL = buffer[offset]; offset += 1;
            double dataH = buffer[offset]; offset += 1;
            resp.intervalOfWaveLen = dataL + dataH * 256;

            // 数据点数
            int iDataL = buffer[offset]; offset += 1;
            int iDataH = buffer[offset]; offset += 1;
            resp.dataNum = iDataL + iDataH * 256;

            // 通道数
            iDataL = buffer[offset]; offset += 1;
            iDataH = buffer[offset]; offset += 1;
            resp.channelNum = iDataL + iDataH * 256;

            // 返回数据帧数
            iDataL = buffer[offset]; offset += 1;
            iDataH = buffer[offset]; offset += 1;
            resp.frameNum = iDataL + iDataH * 256;

            return 0;
        }
        #endregion

        #region 光谱消息的解析和封装
        /// <summary>
        /// 封装光谱请求消息
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        static public int MakeSpectrumReqPackage(ref byte[] buffer, SpectrumReq req)
        {
            int length = 0;
            buffer[0] = req.head.cmd1; length += 1;
            buffer[1] = req.head.cmd2; length += 1;
            buffer[2] = (byte)req.chID; length += 1;
            if (req.sampleQuantity > 1)
            {
                buffer[3] = (byte)req.sampleQuantity; length += 1;
                buffer[4] = 0x00; length += 1;
                buffer[5] = 0x00; length += 1;
            }


            return length;
        }

        /// <summary>
        /// 解析光谱消息
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="dataCounts"></param>
        /// <param name="ssResp"></param>
        /// <param name="resp"></param>
        /// <returns></returns>
        public static int ParseSpectrumZDataPackage(byte[] buffer, int dataCounts, SpectrumSummaryResp ssResp, ref SpectrumZData resp)
        {
            if (dataCounts <= 0)
            {
                return -1;
            }
            int offset = 0;

            // 解析头部
            resp.head.cmd1 = 0x01;
            resp.head.cmd2 = 0x16;
            offset += 2;

            // 通道号
            resp.spectrumData.channelNo = buffer[offset] + 1; offset += 1;

            // 包号
            int pkgNo = buffer[offset]; offset += 1;
            resp.spectrumData.subPkgNo = pkgNo;

            // 数据个数
            //int DataCountsPerPkg = 500;
            resp.spectrumData.data = new double[dataCounts];
            try
            {
                // 波长起始值
                for (int i = 0; i < dataCounts; i++)
                {
                    byte dataL = buffer[offset]; offset += 1;
                    byte dataH = buffer[offset]; offset += 1;
                    UInt16 uValue = (UInt16)(dataL + dataH * 256);
                    Int16 value = (Int16)uValue;

                    resp.spectrumData.data[i] = value / 10.0;
                }
            }
            catch (Exception)
            {

            }

            resp.spectrumData.startWaveLen = ssResp.waveLenStartValue + ssResp.intervalOfWaveLen / 1000 * (500) * pkgNo;
            resp.spectrumData.interval = ssResp.intervalOfWaveLen;
            resp.spectrumData.counts = dataCounts;
            resp.spectrumData.pkgNo = 0;
            resp.spectrumData.nSubPkg = ssResp.frameNum - 1;

            return 0;
        }
        #endregion

        #region 读取通道参数 package 封装和解析
        /// <summary>
        /// 封装读取通道参数请求
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        static public int MakeReadChannelParameterReqPackage(ref byte[] buffer, ReadChannelParameterReq req)
        {
            int offset = 0;
            buffer[offset] = req.head.cmd1; offset += 1;
            buffer[offset] = req.head.cmd2; offset += 1;

            return offset;
        }
        /// <summary>
        /// 解析通道参数
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="resp"></param>
        /// <returns></returns>
        static public int ParseReadChannelParameterRespPackage(byte[] buffer, ref ReadChannelParameterResp resp)
        {
            int offset = 0;

            //解析头部
            resp.head.cmd1 = buffer[0];
            resp.head.cmd2 = buffer[1];
            offset += 2;
            //状态
            resp.status = buffer[offset]; offset++;
            //通道数
            int nChannel = buffer[offset]; offset++;
            if (nChannel > 0)
            {
                resp.nChannel = nChannel;
                resp.param = new ChannelParameter[nChannel];

                for (int i = 0; i < nChannel; i++)
                {
                    resp.param[i] = new ChannelParameter();
                    resp.param[i].threshold = BitConverter.ToInt16(buffer, offset); offset += 2;
                    resp.param[i].refThreshold = BitConverter.ToInt16(buffer, offset); offset += 2;
                    resp.param[i].width = BitConverter.ToInt16(buffer, offset); offset += 2;
                    resp.param[i].widthLevel = BitConverter.ToInt16(buffer, offset); offset += 2;
                    resp.param[i].isValley = buffer[offset]; offset++;
                    offset++;//预留
                }
            }

            return 0;
        }
        #endregion

        #region 设置通道参数 package 封装和解析
        /// <summary>
        /// 封装设置通道参数请求
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        static public int MakeWriteChannelParameterReqPackage(ref byte[] buffer, WriteChannelParameterReq req)
        {
            int offset = 0;
            buffer[offset] = req.head.cmd1; offset += 1;
            buffer[offset] = req.head.cmd2; offset += 1;

            //通道号
            buffer[offset] = (byte)req.chID; offset += 1;
            offset += 1;//预备

            DataConverter.Int16ToBytes(buffer, offset, (Int16)req.param.threshold); offset += 2;
            DataConverter.Int16ToBytes(buffer, offset, (Int16)req.param.refThreshold); offset += 2;
            DataConverter.Int16ToBytes(buffer, offset, (Int16)req.param.width); offset += 2;
            DataConverter.Int16ToBytes(buffer, offset, (Int16)req.param.widthLevel); offset += 2;
            buffer[offset] = (byte)req.param.isValley; offset += 1;

            return offset;
        }
        /// <summary>
        /// 解析设置通道参数返回值
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="resp"></param>
        /// <returns></returns>
        static public int ParseWriteChannelParameterRespPackage(byte[] buffer, ref WriteChannelParameterResp resp)
        {
            int offset = 0;
            //解析头部
            resp.head.cmd1 = buffer[offset]; offset += 1;
            resp.head.cmd2 = buffer[offset]; offset += 1;

            //设备扫描频率
            resp.chID = buffer[offset]; offset += 1;
            resp.status = buffer[offset]; offset += 1;


            return 0;
        }

        #endregion


        #region 读取设备频率
        /// <summary>
        /// 封装读取采集频率请求
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="req"></param>
        /// <returns></returns>
        static public int MakeReadDevFrequencyReqPackage(ref byte[] buffer, ReadDevFrequencyReq req)
        {
            int offset = 0;
            buffer[offset] = req.head.cmd1; offset += 1;
            buffer[offset] = req.head.cmd2; offset += 1;

            return offset;
        }

        /// <summary>
        /// 解析读取采集频率返回值
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="resp"></param>
        /// <returns></returns>
        static public int ParseDevFrequencyRespPackage(byte[] buffer, ref ReadDevFrequencyResp resp)
        {
            int offset = 0;
            //解析头部
            resp.head.cmd1 = buffer[offset]; offset += 1;
            resp.head.cmd2 = buffer[offset]; offset += 1;

            //设备扫描频率
            short netValue = (short)BitConverter.ToUInt16(buffer, offset);
            resp.frequency = netValue;
            offset += 2;

            return 0;
        }
        #endregion


        #endregion
    }





    #region 协议相关数据结构

    public struct PackageHead
    {
        public byte cmd1;
        public byte cmd2;
    }

    public class MessageBase
    {
        public PackageHead head;
    }

    public class StartControl : MessageBase
    {
        public const byte START = 0x55;
        public const byte STOP = 0x00;
        public byte startFlag;
    }

    /// <summary>
    /// 设备基本参数请求消息
    /// </summary>
    public class ReadDeviceBaseInfoReq : MessageBase
    {

    }

    /// <summary>
    /// 设备基本参数应答消息
    /// </summary>
    public class ReadDeviceBaseInfoResp : MessageBase
    {
        public string productModel; // 产品型号
        public string seriesNumber; // 序列号
        public string version; // 版本
        public byte[] deviceIP = new byte[4]; // IP地址
        public int devicePort; // 端口
        public byte[] deviceMac = new byte[6]; // MAC地址
        public byte[] destIP = new byte[4]; // 目的IP地址
        public int destPort; // 目的端口
        public double tempValue; // 温度
        public int startFlag; // 启停标志
        public int nchannel; // 通道数
        public byte[] netMask = new byte[4]; // 子网掩码
        public byte[] gateWay = new byte[4]; // 网关IP
        public byte reserved1; // reserved1
        public byte[] reportServerIP1 = new byte[4]; // IP地址
        public int reportServerPort1; // 端口
        public byte[] reportServerIP2 = new byte[4]; // IP地址
        public int reportServerPort2; // 端口
        public byte[] reportServerIP3 = new byte[4]; // IP地址
        public int reportServerPort3; // 端口
        public uint timeInterval; // 时间间隔（毫秒）
    }

    /// <summary>
    /// 波长消息
    /// </summary>
    public class Wave : QueueData
    {
        public string serialNo;
        public int nChannel;
        public byte cmd; // 存储协议
        public ChannelGrating[] chGratting;
    }
    /// <summary>
    /// 每个通道的光栅波长
    /// </summary>
    public struct ChannelGrating
    {
        public int chID; // 通道号
        public int ngrating; // 光栅数
        public char reserved1;
        public char reserved2;
        public double[] waveValueArray; // 光栅的波长数据
        public double[] dBmValue;  // 强度数据
    }

    // 光谱请求消息
    public class SpectrumReq : MessageBase
    {
        public int chID; // 通道号
        public int sampleQuantity; // 降采样数，分母
    }

    /// <summary>
    /// 通道参数
    /// </summary>
    public class ChannelParameter
    {
        public int chID;
        public int threshold; // 绝对门限
        public int refThreshold; // 相对门限
        public int width; // 识别宽度
        public int widthLevel; // 宽度衰减
        public int isValley; // 是否是波谷
    }

    /// <summary>
    /// 读取通道参数请求
    /// </summary>
    public class ReadChannelParameterReq : MessageBase
    {

    }
    public class ReadChannelParameterResp : MessageBase
    {
        public string serialNo; // 设备序列号
        public int status; // 状态
        public int nChannel; // 通道数
        public ChannelParameter[] param; // 参数值
    }

    /// <summary>
    /// 设置通道参数请求
    /// </summary>
    public class WriteChannelParameterReq : MessageBase
    {
        public int chID; // 通道号（从0开始）
        public ChannelParameter param; // 通道参数
    }
    /// <summary>
    /// 设置通道参数应答
    /// </summary>
    public class WriteChannelParameterResp : MessageBase
    {
        public int chID; // 通道号
        public int status; // 状态
    }

    /// <summary>
    /// 读取设备扫描频率请求
    /// </summary>
    public class ReadDevFrequencyReq : MessageBase
    {

    }
    public class ReadDevFrequencyResp : MessageBase
    {
        public int frequency; // 扫描频率
    }

    #region 光谱相关
    /// <summary>
    /// 光谱Flag
    /// </summary>
    public enum SpectrumFlag
    {
        NONE,
        PEAK, // 波峰
        TROUGH  // 波谷
    };
    /// <summary>
    /// 光谱和功率Item
    /// </summary>
    public struct SpectrumItem
    {
        public double waveLen; // 波长值
        public double dBmValue; // 功率
        public int index; // 在数据中索引值
        public SpectrumFlag flag; // 标识
    }
    public struct PeakValueItem
    {
        public double waveLen; // 波长值
        public double dBmValue; // 功率
    }
    public class SpectrumData : QueueData
    {
        public int chID; // 通道号
        public double startWaveLen; // 波长起始值
        public double interval; // 波长间隔
        public SpectrumItem[] itemArray = new SpectrumItem[0]; // 光谱数据
        public PeakValueItem[] peakValueArray = new PeakValueItem[0]; // PEAK值
    }

    public class SpectrumAcqData
    {
        public int pkgNo;  // 包号
        public int nSubPkg; // 分包数
        public int subPkgNo; // 分包号
        public int channelNo;// 通道号
        public double startWaveLen;//起始波长
        public double interval;//波长间隔
        public int counts;//光谱强度个数
        public double[] data;//光谱强度数据
    }
    public class SpectrumZData : QueueData
    {
        public PackageHead head;
        public SpectrumAcqData spectrumData;
        public SpectrumZData()
        {
            spectrumData = new SpectrumAcqData();
        }
    }

    /// <summary>
    /// 光谱的summary请求消息
    /// </summary>
    public class SpectrumSummaryReq : MessageBase
    {

    }
    /// <summary>
    /// 光谱的summary应答消息
    /// </summary>
    public class SpectrumSummaryResp : MessageBase
    {
        public double waveLenStartValue; // 起始波长值
        public double intervalOfWaveLen; // 波长间隔
        public int dataNum; // 点数
        public int channelNum; // 通道数
        public int frameNum; // 帧数
        public byte sampleQuantity;  // 如果不为0x00说明设备有降采样功能 

        public SpectrumSummaryResp() { }

        public SpectrumSummaryResp(SpectrumSummaryResp resp, int sampleQuantity)
        {
            this.waveLenStartValue = resp.waveLenStartValue;
            this.intervalOfWaveLen = resp.intervalOfWaveLen * sampleQuantity;
            this.dataNum = resp.dataNum / sampleQuantity + 1;
            this.channelNum = resp.channelNum;
            double v = (resp.frameNum - 1) / (double)sampleQuantity;
            if (v > (int)v)
            {
                v = v + 1;
            }
            this.frameNum = (int)v + 1;
            this.sampleQuantity = resp.sampleQuantity;
        }

        public SpectrumSummaryResp(SpectrumSummaryResp resp)
        {
            this.waveLenStartValue = resp.waveLenStartValue;
            this.intervalOfWaveLen = resp.intervalOfWaveLen;
            this.dataNum = resp.dataNum;
            this.channelNum= resp.channelNum;
            this.frameNum = resp.frameNum;
            this.sampleQuantity = resp.sampleQuantity;
        }

        public SpectrumSummaryResp Clone()
        {
            return new SpectrumSummaryResp(this);
        }
    }
    #endregion
    #endregion
}
